#include "manano_common.h"

#include "mdtx-online/indicator/indicator_type_s2_var.h"
namespace indi = mdtx::online::indicator;

using variance = unary1<indi::variance>;
using variance_ew = unary1<indi::variance_ew>;
using variance_cu = unary1<indi::variance_cu>;
using variance_vw = binary1<indi::variance_vw>;
using variance_cuvw = binary1<indi::variance_cuvw>;

using volatility = unary1<indi::volatility>;
using volatility_ew = unary1<indi::volatility_ew>;
using volatility_cu = unary1<indi::volatility_cu>;
using volatility_vw = binary1<indi::volatility_vw>;
using volatility_cuvw = binary1<indi::volatility_cuvw>;

using ulcer = unary1<indi::ulcer>;

void bind_indi_s2_var(py::module &m)
{
    auto mod = m.def_submodule("var", "Rolling variance and volatility");
    {
        auto v = py::class_<variance>(mod, "var")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &variance::run, py::arg("x"), "Run calc")
                     .def("run", &variance::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Rolling variance
                    Args:
                        period (int) : rolling window period)mydoc";
    }
    {
        auto v = py::class_<variance_ew>(mod, "var_ew")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &variance_ew::run, py::arg("x"), "Run calc")
                     .def("run", &variance_ew::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Exponentially weighted rolling variance
                    Args:
                        period (int) : rolling window period)mydoc";
    }
    {
        auto v = py::class_<variance_cu>(mod, "var_cu")
                     .def(py::init())
                     .def("run", &variance_cu::run, py::arg("x"), "Run calc")
                     .def("run", &variance_cu::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Cumulative variance)mydoc";
    }
    {
        auto v = py::class_<variance_vw>(mod, "var_vw")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &variance_vw::run, py::arg("x"), py::arg("w"), "Run calc")
                     .def("run", &variance_vw::run2, py::arg("x"), py::arg("w"), "Run batch calc");
        v.doc() = R"mydoc(
                    Volume weighted rolling variance
                    Args:
                        period (int) : rolling window period)mydoc";
    }
    {
        auto v = py::class_<variance_cuvw>(mod, "var_cuvw")
                     .def(py::init())
                     .def("run", &variance_cuvw::run, py::arg("x"), py::arg("w"), "Run calc")
                     .def("run", &variance_cuvw::run2, py::arg("x"), py::arg("w"), "Run batch calc");
        v.doc() = R"mydoc(
                    Volume weighted cumulative variance)mydoc";
    }

    {
        auto v = py::class_<volatility>(mod, "volatility")
                     .def(py::init<int, int>(), py::arg("period"), py::arg("annualise") = 250)
                     .def("run", &volatility::run, py::arg("x"), "Run calc")
                     .def("run", &volatility::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Annualised rolling volatility, log return
                    Args:
                        period (int) : rolling window period
                        annualise (int) : trading days per annum)mydoc";
    }
    {
        auto v = py::class_<volatility_ew>(mod, "volatility_ew")
                     .def(py::init<int, int>(), py::arg("period"), py::arg("annualise") = 250)
                     .def("run", &volatility_ew::run, py::arg("x"), "Run calc")
                     .def("run", &volatility_ew::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Annualised exponentially weighted rolling volatility, log return
                    Args:
                        period (int) : rolling window period
                        annualise (int) : trading days per annum)mydoc";
    }
    {
        auto v = py::class_<volatility_cu>(mod, "volatility_cu")
                     .def(py::init<int>(), py::arg("annualise") = 250)
                     .def("run", &volatility_cu::run, py::arg("x"), "Run calc")
                     .def("run", &volatility_cu::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Annualised cumulative volatility, log return
                    Args:
                        annualise (int) : trading days per annum)mydoc";
    }
    {
        auto v = py::class_<volatility_vw>(mod, "volatility_vw")
                     .def(py::init<int, int>(), py::arg("period"), py::arg("annualise") = 250)
                     .def("run", &volatility_vw::run, py::arg("x"), py::arg("w"), "Run calc")
                     .def("run", &volatility_vw::run2, py::arg("x"), py::arg("w"), "Run batch calc");
        v.doc() = R"mydoc(
                    Annualised volume weighted rolling volatility, ARITHMETIC return
                    Args:
                        period (int) : rolling window period
                        annualise (int) : trading days per annum)mydoc";
    }
    {
        auto v = py::class_<volatility_cuvw>(mod, "volatility_cuvw")
                     .def(py::init<int>(), py::arg("annualise") = 250)
                     .def("run", &volatility_cuvw::run, py::arg("x"), py::arg("w"), "Run calc")
                     .def("run", &volatility_cuvw::run2, py::arg("x"), py::arg("w"), "Run batch calc");
        v.doc() = R"mydoc(
                    Annualised volume weighed cumulative volatility, ARITHMETIC return
                    Args:
                        annualise (int) : trading days per annum)mydoc";
    }

    {
        auto v = py::class_<ulcer>(mod, "ulcer")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &ulcer::run, py::arg("x"), "Run calc")
                     .def("run", &ulcer::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Ulcer index (var downside risk)
                    Args:
                        period (int) : rolling window period)mydoc";
    }
}
